package com.easy.dfc.web;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.easy.core.web.BaseController;
import com.easy.dfc.Utils.*;
import com.easy.dfc.Utils.Error;
import com.easy.dfc.entity.*;
import com.easy.dfc.service.OrderActionService;
import com.easy.dfc.service.OrderSetService;
import com.easy.dfc.service.TradeSetService;
import com.easy.dfc.service.UsersetService;
import com.pingplusplus.Pingpp;
import com.pingplusplus.model.Charge;
import com.pingplusplus.model.Refund;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by VULCANTSeries on 2017/6/12.
 */
@Controller
@RequestMapping("${apiPath}/Pay")
public class PayController extends BaseController {

    @Resource
    private UsersetService usersetService;

    @Resource
    private OrderSetService orderSetService;

    @Resource
    private TradeSetService tradeSetService;

    @Resource
    private OrderActionService orderActionService;

    /**
     * 付款
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/OrderStatusNum", method = RequestMethod.POST)
    public ResponseEntity<JSONObject> OrderStatusNum(HttpServletRequest request) {
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.setContentType(MediaType.APPLICATION_JSON);
        JSONObject jsonObject = new JSONObject();
        try {
            String userId = request.getParameter("UserId");
            String token = request.getParameter("Token");
            if (!usersetService.VerifyToken(userId, token)) {
                jsonObject.put("Err", Error.ValidFailed);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            String OrderItemNoList = JSONArray.parseArray(request.getParameter("OrderItemNoList")).get(0).toString();

            OrderSetWithBLOBs orderSetWithBLOBs = orderSetService.selectItemNo(OrderItemNoList);
            if (!Util.ToUuidString(userId.replaceAll("-", "")).equals(orderSetService.selectUser(orderSetWithBLOBs.getId()).getUserid())) {
                jsonObject.put("Err", Error.OrderNotUser);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            if (orderSetWithBLOBs.getStatus() != OrderStutas.Unpaid) {
                jsonObject.put("Err", Error.OrderStutsErr);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            String subject = "大风车商城订单：" + orderSetWithBLOBs.getItemno();
            String body = orderSetWithBLOBs.getItemno() + ";日期:" + new SimpleDateFormat("yyyyMMdd").format(new Date());
            BigDecimal amount = orderSetWithBLOBs.getAmount();
            Pingpp.apiKey = Util.getApiKey(request);
            Pingpp.privateKeyPath = Util.getPrivateKeyPath(request);
            Charge charge = null;
            String channel = "alipay";
            Map<String, Object> chargeMap = new HashMap<String, Object>();
            chargeMap.put("amount", amount.multiply(new BigDecimal(100)));//订单总金额, 人民币单位：分（如订单总金额为 1 元，此处请填 100）
            chargeMap.put("currency", "cny");
            chargeMap.put("subject", subject);
            chargeMap.put("body", body);
            String orderNo = OrderItemNoList;
            chargeMap.put("order_no", orderNo);// 推荐使用 8-20 位，要求数字或字母，不允许其他字符
            chargeMap.put("channel", channel);// 支付使用的第三方支付渠道取值，请参考：https://www.pingxx.com/api#api-c-new
            chargeMap.put("client_ip", Util.getIpAddress(request)); // 发起支付请求客户端的 IP 地址，格式为 IPV4，如: 127.0.0.1
            Map<String, String> app = new HashMap<String, String>();
            app.put("id", "app_1SKenTmfzvHOuL0G");
            chargeMap.put("app", app);

            // extra 取值请查看相应方法说明
            chargeMap.put("extra", channelExtra(channel));

            //发起交易请求
            charge = Charge.create(chargeMap);
            // 传到客户端请先转成字符串 .toString(), 调该方法，会自动转成正确的 JSON 字符串
            String chargeString = charge.toString();
            TradeSet tradeSet = tradeSetService.selectByItemNo(orderSetWithBLOBs.getItemno());
            if (tradeSet != null) {
                tradeSet.setChargeId(charge.getId());
                tradeSetService.updateByPrimaryKeySelective(tradeSet);
            } else {
                tradeSet = new TradeSet();
                tradeSet.setChargeId(charge.getId());
                tradeSet.setAmount(amount);
                tradeSet.setCreated(new Date());
                tradeSet.setItemno(orderSetWithBLOBs.getItemno());
                tradeSetService.insertSelective(tradeSet);
            }
            jsonObject = JSONObject.parseObject(JsonUtil.toErrJson(Error.OK, chargeString));
        } catch (Exception e) {
            jsonObject.put("Err", Error.OtherError);
            return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
        }
        return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
    }

    public String randomString(int length) {
        String str = new BigInteger(130, new SecureRandom()).toString(32);
        return str.substring(0, length);
    }

    private Map<String, Object> channelExtra(String channel) {
        Map<String, Object> extra = new HashMap<>();

        switch (channel) {
            case "alipay":
                extra = alipayExtra();
                break;
        }

        return extra;
    }

    // extra 根据渠道会有不同的参数

    private Map<String, Object> alipayExtra() {
        Map<String, Object> extra = new HashMap<>();

        // 可选，开放平台返回的包含账户信息的 token（授权令牌，商户在一定时间内对支付宝某些服务的访问权限）。通过授权登录后获取的  alipay_open_id ，作为该参数的  value ，登录授权账户即会为支付账户，32 位字符串。
        // extra.put("extern_token", "TOKEN");

        // 可选，是否发起实名校验，T 代表发起实名校验；F 代表不发起实名校验。
        extra.put("rn_check", "F");

        return extra;
    }

    /**
     * 付款成功
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/PaySuccees", method = RequestMethod.POST)
    public ResponseEntity<JSONObject> PaySuccees(HttpServletRequest request) {
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.setContentType(MediaType.APPLICATION_JSON);
        JSONObject jsonObject = new JSONObject();
        try {
            String json = GetRequestJsonUtils.getRequestPostStr(request);
            if (WebhooksVerify.verifyData(json, request.getHeader("x-pingplusplus-signature"), WebhooksVerify.getPubKey(request))) {
                JSONObject object = JSONObject.parseObject(json);
                String chargeId = JSONObject.parseObject(JSONObject.parseObject(object.get("data").toString()).get("object").toString()).get("id").toString();
                TradeSet tradeSet = tradeSetService.selectBychargeId(chargeId);
                if (tradeSet != null) {
                    tradeSet.setChannel("支付宝");
                    tradeSetService.updateByPrimaryKeySelective(tradeSet);
                    OrderSetWithBLOBs orderSetWithBLOBs = orderSetService.selectItemNo(tradeSet.getItemno());
                    orderSetWithBLOBs.setStatus(OrderStutas.Paid);
                    orderSetService.updateByPrimaryKeySelective(orderSetWithBLOBs);
                    Util.AddOrderAction(orderSetWithBLOBs.getId(), orderActionService, OrderStutas.Paid);
                }
            }
            jsonObject.put("Err", Error.OK);
        } catch (Exception e) {
            jsonObject.put("Err", Error.OtherError);
            return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
        }
        return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
    }

    /**
     * 买家发起退款
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/dealerRefund", method = RequestMethod.POST)
    public ResponseEntity<JSONObject> dealerRefund(HttpServletRequest request) {
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.setContentType(MediaType.APPLICATION_JSON);
        JSONObject jsonObject = new JSONObject();
        try {
            String userId = request.getParameter("UserId");
            String token = request.getParameter("Token");
            if (!usersetService.VerifyToken(userId, token)) {
                jsonObject.put("Err", Error.ValidFailed);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            String OrderItemNoList = JSONArray.parseArray(request.getParameter("OrderItemNoList")).get(0).toString();
            OrderSetWithBLOBs orderSetWithBLOBs = orderSetService.selectItemNo(OrderItemNoList);
            if (!Util.ToUuidString(userId.replaceAll("-", "")).equals(orderSetService.selectUser(orderSetWithBLOBs.getId()).getUserid())) {
                jsonObject.put("Err", Error.OrderNotUser);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            int status = orderSetWithBLOBs.getStatus();
            if (status != OrderStutas.Paid && status != OrderStutas.Delivery && status != OrderStutas.TakeDelivery) {
                jsonObject.put("Err", Error.OrderStutsErr);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            orderSetWithBLOBs.setStatus(OrderStutas.Refuning);
            orderSetService.updateByPrimaryKeySelective(orderSetWithBLOBs);
            Util.AddOrderAction(orderSetWithBLOBs.getId(), orderActionService, OrderStutas.Refuning);
            jsonObject.put("Err", Error.OK);
        } catch (Exception e) {
            jsonObject.put("Err", Error.OtherError);
            return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
        }
        return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
    }

    /**
     * 卖家确认退款
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/OrderRefund", method = RequestMethod.POST)
    public ResponseEntity<JSONObject> OrderRefund(HttpServletRequest request) {
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.setContentType(MediaType.APPLICATION_JSON);
        JSONObject jsonObject = new JSONObject();
        try {
            String userId = request.getParameter("UserId");
            String token = request.getParameter("Token");
            if (!usersetService.VerifyToken(userId, token)) {
                jsonObject.put("Err", Error.ValidFailed);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            String OrderItemNoList = JSONArray.parseArray(request.getParameter("OrderItemNoList")).get(0).toString();
            OrderSetWithBLOBs orderSetWithBLOBs = orderSetService.selectItemNo(OrderItemNoList);
            if (!Util.ToUuidString(userId.replaceAll("-", "")).equals(orderSetService.selectUserByFactory(orderSetWithBLOBs.getId()).getUserid())) {
                jsonObject.put("Err", Error.OrderNotUser);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            TradeSet tradeSet = tradeSetService.selectByItemNo(orderSetWithBLOBs.getItemno());
            if (orderSetWithBLOBs.getStatus() != OrderStutas.Refuning) {
                jsonObject.put("Err", Error.OrderStutsErr);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("description", " ");
            params.put("amount", orderSetWithBLOBs.getAmount().multiply(new BigDecimal(100)));
            Refund refund = Refund.create(tradeSet.getChargeId(), params);
            jsonObject = JSONObject.parseObject(JsonUtil.toErrJson(Error.OK, refund.toString()));
        } catch (Exception e) {
            jsonObject.put("Err", Error.OtherError);
            return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
        }
        return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
    }

    /**
     * 退款成功
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/RefundSuccees", method = RequestMethod.POST)
    public ResponseEntity<JSONObject> RefundSuccees(HttpServletRequest request) {
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.setContentType(MediaType.APPLICATION_JSON);
        JSONObject jsonObject = new JSONObject();
        try {
            String json = GetRequestJsonUtils.getRequestPostStr(request);
            if (WebhooksVerify.verifyData(json, request.getHeader("x-pingplusplus-signature"), WebhooksVerify.getPubKey(request))) {
                JSONObject object = JSONObject.parseObject(json);
                String chargeId = JSONObject.parseObject(JSONObject.parseObject(object.get("data").toString()).get("object").toString()).get("id").toString();
                TradeSet tradeSet = tradeSetService.selectBychargeId(chargeId);
                if (tradeSet != null) {
                    OrderSetWithBLOBs orderSetWithBLOBs = orderSetService.selectItemNo(tradeSet.getItemno());
                    orderSetWithBLOBs.setStatus(OrderStutas.Refund);
                    orderSetService.updateByPrimaryKeySelective(orderSetWithBLOBs);
                    Util.AddOrderAction(orderSetWithBLOBs.getId(), orderActionService, OrderStutas.Refund);
                }
            }
            jsonObject.put("Err", Error.OK);
        } catch (Exception e) {
            jsonObject.put("Err", Error.OtherError);
            return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
        }
        return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
    }

    /**
     * 卖家拒绝退款
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/Refuse", method = RequestMethod.POST)
    public ResponseEntity<JSONObject> Refuse(HttpServletRequest request) {
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.setContentType(MediaType.APPLICATION_JSON);
        JSONObject jsonObject = new JSONObject();
        try {
            String userId = request.getParameter("UserId");
            String token = request.getParameter("Token");
            if (!usersetService.VerifyToken(userId, token)) {
                jsonObject.put("Err", Error.ValidFailed);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            int orderId = Integer.parseInt(request.getParameter("orderId"));
            Userset userset = orderSetService.selectUserByFactory(orderId);
            if (!userId.equals(userset.getUserid().replaceAll("-", ""))) {
                jsonObject.put("Err", Error.OrderNotUser);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            OrderSetWithBLOBs orderSetWithBLOBs = orderSetService.selectById(orderId);
            if (orderSetWithBLOBs.getStatus() != OrderStutas.Refuning) {
                jsonObject.put("Err", Error.OrderStutsErr);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            orderSetWithBLOBs.setStatus(OrderStutas.Refuse);
            orderSetService.updateByPrimaryKeySelective(orderSetWithBLOBs);
            //记录
            Util.AddOrderAction(orderId, orderActionService, OrderStutas.Refuse);
            jsonObject.put("Err", Error.OK);
        } catch (Exception e) {
            jsonObject.put("Err", Error.OtherError);
            return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
        }
        return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
    }

    /**
     * 买家取消退款
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/CancelRefund", method = RequestMethod.POST)
    public ResponseEntity<JSONObject> CancelRefund(HttpServletRequest request) {
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.setContentType(MediaType.APPLICATION_JSON);
        JSONObject jsonObject = new JSONObject();
        try {
            String userId = request.getParameter("UserId");
            String token = request.getParameter("Token");
            if (!usersetService.VerifyToken(userId, token)) {
                jsonObject.put("Err", Error.ValidFailed);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            int orderId = Integer.parseInt(request.getParameter("orderId"));
            Userset userset = orderSetService.selectUser(orderId);
            if (!userId.equals(userset.getUserid().replaceAll("-", ""))) {
                jsonObject.put("Err", Error.OrderNotUser);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            OrderSetWithBLOBs orderSetWithBLOBs = orderSetService.selectById(orderId);
            if (orderSetWithBLOBs.getStatus() != OrderStutas.Refuning) {
                jsonObject.put("Err", Error.OrderStutsErr);
                return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
            }
            //将订单状态改为订单退款前的状态
            List<OrderAction> orderActionList = orderActionService.selectByOrderId(orderId);
            orderSetWithBLOBs.setStatus(orderActionList.get(orderActionList.size() - 2).getAction());
            orderSetService.updateByPrimaryKeySelective(orderSetWithBLOBs);
            //记录
            Util.AddOrderAction(orderId, orderActionService, OrderStutas.CancelRefund);
            jsonObject.put("Err", Error.OK);
        } catch (Exception e) {
            jsonObject.put("Err", Error.OtherError);
            return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
        }
        return new ResponseEntity<JSONObject>(jsonObject, responseHeaders, HttpStatus.OK);
    }
}
